home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / SDKs / AutoPay SDK Mac R1.02 / AutoPay™ Development / other routines you may want / routines you may want.c
Encoding:
Text File  |  1996-04-20  |  12.1 KB  |  500 lines  |  [TEXT/MMCC]

  1.  
  2. // ****************************************************************
  3. //
  4. // Copyright 1995-96 Release Software Corporation.
  5. // Release Software was formerly Digital Money, Inc.
  6. // You may use this source code in your own applications.
  7. //
  8. // *******************************************************************
  9. //
  10. // Supplemental routines for use with Release Software's AutoPay Module.
  11. // These routines were written for Think C 5.0, modified to run under Metrowerks CodeWarrior,
  12. // and should be immediately useable with other C environments.
  13.  
  14. // Feel free to use these routines in you own applications.
  15. // See the AutoPay manual, Chapter 4, for more information.
  16.  
  17. // This file uses ANSI routines.
  18.  
  19. // Updated 4/20/1996.
  20. // *******************************************************************
  21.  
  22. // *******************************
  23. // THINGS YOU NEED TO PERSONALIZE:
  24. // *******************************
  25. // See the manual for more info.
  26.  
  27. // Personalize the following three strings:
  28.  
  29. #define kTheCryptoKey         "Put your crypto key here!"
  30. #define kYourProgramName     "YourProgramNameHere"
  31. #define kOwnerResource        'xYxn'                    // This should match your 
  32.                                                 // application's owner resource
  33.                                                 // If you don't know what this is,
  34.                                                 // choose a random 4-char string.
  35. #include <Folders.h>
  36. #include <Files.h>
  37. #include <Script.h>
  38.  
  39. // The keyType structure. See the description below.
  40.  
  41. typedef struct
  42. {
  43.     char            name[60];
  44.     char            verificationCode[60];
  45.     char            serialNumber[30];
  46. }    keyType;
  47.  
  48. // *******************
  49. // Function prototypes
  50. // *******************
  51.  
  52. OSErr         readKeyFromDisk             (keyType *key);
  53. OSErr         writeKeyToDisk             (keyType *key);
  54. Boolean         isProgramRegistered         (void);
  55. char             *myEncrypt                (char *inputString, char *cryptoKey);
  56. OSErr         saveProgramAsRegistered     (char *theName);
  57. OSErr         saveSerialNumber             (char *theSerialNumber);
  58. void             drawSplashScreen             (int whichColorPictToUse, int whichBWPictToUse);
  59.  
  60. Boolean isProgramRegistered (void)
  61. {
  62.     keyType        theKey;
  63.     char            cryptoKey[50], whatItShouldBe[80];
  64.     OSErr        iErr;
  65.     
  66.     // EXPLANATION:
  67.     //
  68.     // This is a pretty straightforward locking/unlocking mechanism that you can use
  69.     // in your program to see whether a program has been registered (i.e. payed for)
  70.     // or not.
  71.     
  72.     // A brief description follows, but for more details, you should see
  73.     // your AutoPay Developer's Manual.
  74.     
  75.     // What happens is this. The program opens a "key file" which is stored
  76.     // in the preferences folder. The Key File has three components:
  77.     
  78.     //     The registration name :    the name of the user who paid for program
  79.     
  80.     //      The verification code :    a special code that is specific to
  81.     //                                  to the registration name. This proves the
  82.     //                                registration name hasn't been tampered with.
  83.                                     
  84.     //    The serial number        
  85.     
  86.     
  87.     
  88.     iErr=readKeyFromDisk(&theKey);
  89.     
  90.     if (iErr)
  91.     {
  92.         // add your own error handling here if desired
  93.     }
  94.     
  95.     if (strlen((char*)theKey.name)==0)
  96.     {
  97.         // Either the key file doesn't exist or the name has been tampered
  98.         // with. So treat this as an unregistered copy.
  99.         
  100.         return (false);
  101.     }
  102.     
  103.     // A name *does* exist. Now the program looks at the verification code. 
  104.     // There is some, *unobvious* cryptographic relationship between the name and
  105.     // the verification code, but only you as the developer knows it. This stops
  106.     // hackers from examining an officially registered copy of your app and figuring
  107.     // out how to write a "correct" result string based on a seed string of his choice.
  108.     
  109.     if (strlen((char*)theKey.verificationCode)==0)
  110.     {
  111.         return (false);
  112.     }
  113.         
  114.     strcpy(cryptoKey,kTheCryptoKey);
  115.     
  116.     // Feed the name into the encryption routine to find out what the
  117.     // verification code *should* be. Then see if it's a match.
  118.     
  119.     strcpy((char*)&whatItShouldBe, myEncrypt((char*)&theKey.name,cryptoKey) );
  120.     if ( strcmp    (
  121.             whatItShouldBe,            // If the resultString is
  122.             &theKey.verificationCode        // identical to what you'd expect to get
  123.                 ) == 0 )                 // given your program's cryptoKey,
  124.                                         
  125.         {    
  126.             return(true);                // then this is a valid, registered copy
  127.         }
  128.     else
  129.         {
  130.             return(false);                // ...otherwise it isn't
  131.         }
  132. }
  133.  
  134. OSErr saveSerialNumber (char *theSerialNumber)
  135. {
  136.     keyType theKey;
  137.     
  138.  
  139.     readKeyFromDisk(&theKey);
  140.     strcpy((char*)&theKey.serialNumber,theSerialNumber);
  141.     writeKeyToDisk(&theKey);
  142. }
  143.  
  144.  
  145.     
  146. OSErr saveProgramAsRegistered (char *theName)
  147. {
  148.     OSErr     iErr;
  149.     keyType theKey;
  150.     char     *theResult;
  151.     char    cryptoKey[50];
  152.     
  153.     // First the program stores the name string in the appropriate place.
  154.     
  155.     iErr=readKeyFromDisk(&theKey);
  156.     if (iErr)
  157.         return (iErr);
  158.         
  159.     // Next it stores the Verification Code, which is encrypted based on your
  160.     // cryptoKey. See the AutoPay manual for more information.
  161.     
  162.     strcpy(cryptoKey,kTheCryptoKey);
  163.     strcpy ((char*)&theKey.verificationCode, myEncrypt(theName,cryptoKey) );
  164.     
  165.     strcpy((char*)&theKey.name,theName);
  166.     iErr=writeKeyToDisk(&theKey);
  167.     if (iErr)
  168.         return (iErr);
  169.         
  170. }
  171.  
  172.  
  173. char *myEncrypt(char *inputString, char *cryptoKey)
  174. {
  175.     long     numCharsInInput;
  176.     int        cryptoCharToUse,i;
  177.     char    charToAdd;
  178.     char    *outputString;
  179.     
  180.     // Given an input string and a cryptoKey (know only to you)
  181.     // this routiner spits out an encrypted version of the input
  182.     // string. Later, you'll be able to compare say, a user's name
  183.     // and it's encrypted version to make sure the user's name hasn't been
  184.     // tampered with.
  185.     
  186.     outputString=NewPtr(strlen(inputString)+1);
  187.     
  188.     numCharsInInput=strlen(inputString);
  189.     cryptoCharToUse=0;
  190.     *outputString='\0';
  191.     
  192.     for (i=0; i<=numCharsInInput-1; i++)
  193.     {
  194.         
  195.         charToAdd=(inputString[i]^cryptoKey[cryptoCharToUse])+28; // ^ is exclusive OR
  196.         
  197.         charToAdd=charToAdd%33; // the remainder of the number after divided by 33
  198.         charToAdd=32+charToAdd;
  199.         outputString[i]=charToAdd;
  200.         
  201.         cryptoCharToUse++;
  202.         if (cryptoCharToUse>strlen(cryptoKey)-1)
  203.             cryptoCharToUse=0;
  204.     }
  205.  
  206.     outputString[i]='\0'; // make sure the output string is terminated with a null
  207.     
  208.     return (outputString);
  209. }
  210.  
  211.  
  212.  
  213. OSErr readKeyFromDisk (keyType *key)
  214. {
  215.  
  216.     OSErr    myErr;
  217.     short    myVRef, i;
  218.     long    myDirID;
  219.     FSSpec    mySpec;
  220.     char    myName[25];
  221.     short        myRef;
  222.     Handle    myHandle;
  223.     int        myRefNum, version;
  224.     long    len;
  225.     long    myLen[6];
  226.     
  227.     // find the "key" file in the system
  228.     
  229.     strcpy(myName,kYourProgramName);
  230.     strcat(myName," Key");
  231.     
  232.     // The "key file" will be stored in the Preferences folder 
  233.     // within the System folder
  234.     
  235.     myErr=FindFolder(kOnSystemDisk,kPreferencesFolderType,kDontCreateFolder, &myVRef, &myDirID);
  236.     
  237.     if (myErr==noErr)
  238.         myErr=FSMakeFSSpec(myVRef, myDirID, CtoPstr(myName), &mySpec);
  239.  
  240.     // If no "key file" exists, return a null key.
  241.     // This will happen the first time the user wants to register.
  242.     
  243.     if (myErr==fnfErr)
  244.     {
  245.         key->name[0]='\0';
  246.         key->verificationCode[0]='\0';
  247.         key->serialNumber[0]='\0';
  248.         return(noErr);
  249.     }
  250.     
  251.     if (myErr==noErr)
  252.         myRefNum=FSpOpenDF(&mySpec, fsRdWrPerm, &myRef);
  253.     else if (myErr!=eofErr) return(myErr);                    // error check
  254.  
  255.     
  256.     myErr=SetFPos(myRef, fsFromStart,0);
  257.     
  258.     if ((myErr!=noErr) && (myErr!=eofErr))
  259.          return(myErr);                                        // error check
  260.     
  261.     // Check the version number of the key file.
  262.     // This really has no use now, but may or may not come in handy in
  263.     // in the future, if you ever decide to change the file format of
  264.     // the key file.
  265.     
  266.     len=2;
  267.     if (myErr==noErr)
  268.     {
  269.         myErr=FSRead(myRef, &len, &version);
  270.     }
  271.     if (version!=1)
  272.         myErr=eofErr; // if this is not version 1, just pretend file doesn't exist
  273.     
  274.     len=sizeof(*key);    
  275.     
  276.     if (myErr==noErr)
  277.     {
  278.         myErr=FSRead(myRef, &len, key);
  279.     }
  280.     
  281.     
  282.     if ((myErr) && (myErr!=eofErr)) return(myErr);         // error check
  283.  
  284.     FSClose(myRef);
  285.     
  286.     return(noErr);
  287.       
  288. }
  289.  
  290. OSErr writeKeyToDisk (keyType *key)
  291. {
  292.     OSErr    myErr;
  293.     short    myVRef, i;
  294.     long    myDirID;
  295.     FSSpec    mySpec;
  296.     char    myName[25];
  297.     int        scrapInt;
  298.     short     myRef,myVol;
  299.     int        myRefNum;
  300.     long    len,fLength=0;
  301.  
  302.     strcpy(myName,kYourProgramName);
  303.     strcat(myName," Key");
  304.  
  305.     myErr=FindFolder(kOnSystemDisk,kPreferencesFolderType,kDontCreateFolder, &myVRef, &myDirID);
  306.     
  307.     if (myErr==noErr)
  308.         myErr=FSMakeFSSpec(myVRef, myDirID, CtoPstr(myName), &mySpec);
  309.  
  310.     if (myErr==fnfErr)
  311.     {
  312.         myErr= FSpCreate(&mySpec, kOwnerResource, 'pref', smSystemScript);
  313.         fLength=0;
  314.     }
  315.     
  316.     if (myErr==noErr)
  317.         myRefNum=FSpOpenDF(&mySpec, fsRdWrPerm, &myRef);
  318.     
  319.     
  320.     if (myErr==noErr)
  321.     {
  322.         myErr=SetFPos(myRef, fsFromStart, 0);        // write at beginning
  323.     }
  324.     
  325.     // Write the version number of the key file
  326.     // for future upgrade capability. This is version 1.
  327.     
  328.     len=2;
  329.     scrapInt=1;
  330.     if (myErr==noErr)
  331.     {
  332.         myErr= FSWrite (myRef, &len, &scrapInt);
  333.         fLength+=len;
  334.     }
  335.     
  336.     // write the actual key data structure
  337.     
  338.     len=sizeof(*key);
  339.     if (myErr==noErr)
  340.     {
  341.         myErr= FSWrite (myRef, &len, key);
  342.         fLength+=len;
  343.     }
  344.  
  345.     myErr=SetEOF(myRef, fLength);
  346.     if (myErr) return(myErr);
  347.     
  348.     if (myErr==noErr)
  349.     {
  350.         myErr=GetVRefNum(myRef, &myVol);                // find volume file is on
  351.     }
  352.     
  353.     if (myErr==noErr)
  354.     {
  355.         FSClose(myRef);
  356.         myErr=FlushVol(nil, myVol);                        // ... and flush it
  357.         if (myErr) return(myErr);
  358.     }
  359.       
  360.     return(myErr);
  361. }
  362.  
  363.  
  364. /********************************/
  365. //        drawSplashScreen                    //
  366. /*******************************/
  367.  
  368. void drawSplashScreen (int whichColorPictToUse, int whichBWPictToUse)
  369. {
  370.  
  371.     GrafPtr        oldPort;
  372.     Boolean        userReacts, hasColor=false;
  373.     SysEnvRec    sysEnv;
  374.     Rect        r,winRect,textBox;
  375.     PicHandle    thePict;
  376.     int         screenWidth,screenHeight,pictWidth,pictHeight,winLeft,winTop;
  377.     WindowPtr    window;
  378.     short        oldFont,oldSize,curPnMode;
  379.     EventRecord    event;
  380.     keyType        theKey;
  381.     char        output[100];
  382.     
  383.     #define        SysEnvironsTrap            0xA090
  384.     #define        UnknownTrap                0xA89F
  385.  
  386.     GetPort(&oldPort);
  387.     
  388.     // First check to see if the computer has color display or not.
  389.     // This will help us decide whether to draw the color picture
  390.     // or the B&W picture.
  391.     
  392.     if ((long)NGetTrapAddress(SysEnvironsTrap, OSTrap) != (long)NGetTrapAddress(UnknownTrap, ToolTrap))
  393.     {
  394.         SysEnvirons(1, &sysEnv);
  395.         
  396.         // Check graphic's device depth    
  397.         if ((*((*((GDHandle)GetGDevice()))->gdPMap))->pixelSize > 1)    
  398.         {
  399.             hasColor = sysEnv.hasColorQD;                        // Does it have color?        
  400.         }
  401.     }
  402.         
  403.     if (hasColor)
  404.         thePict=GetPicture(whichColorPictToUse);        
  405.     else
  406.         thePict=GetPicture(whichBWPictToUse);
  407.  
  408.     r = (*thePict)->picFrame;
  409.     
  410.     pictWidth = r.right - r.left;        // calculate width of picture
  411.     pictHeight = r.bottom - r.top;        // calculate height of picture
  412.     
  413.     
  414.     screenWidth =(qd.screenBits.bounds).right;        // calculate width of screen
  415.     screenHeight =(qd.screenBits.bounds).bottom;    // calculate height of screen
  416.     
  417.     // Center the splash window on the screen:
  418.     
  419.     winLeft=(screenWidth/2)-(pictWidth/2);
  420.     winTop=(screenHeight/2)-(pictHeight/2);
  421.     SetRect(&winRect,winLeft,winTop,winLeft+pictWidth,winTop+pictHeight);
  422.     
  423.     // make a new, temporary window, just big enough to hold your
  424.     // splash screen picture
  425.     window = NewWindow(nil,&winRect,"\p",true,plainDBox,(WindowPtr)-1,false,0);
  426.     
  427.     SetPort(window);
  428.     DrawPicture( thePict,  &(window->portRect) );
  429.     
  430.     // Now draw your text ON TOP OF the picture.
  431.     
  432.     
  433.     TextFont(applFont);
  434.     TextFace(bold);
  435.     
  436.     readKeyFromDisk(&theKey);
  437.     
  438.     if (!isProgramRegistered())
  439.     {
  440.         
  441.         strcpy(output,"This program is not registered.\rYou can register immediately with Digital Money™.\rSee the Apple menu.");
  442.         
  443.         // You may want to change the coordinates where the text box is overlaid
  444.         // on picture window:
  445.         
  446.         TextSize(11);
  447.         SetRect(&textBox,window->portRect.left+2,window->portRect.bottom-80,window->portRect.right-2,window->portRect.bottom-30);
  448.         TextBox(output,strlen(output),&textBox,teJustLeft);
  449.     
  450.     }
  451.     else
  452.     {
  453.  
  454.         sprintf(output,"This copy is registered to %s.",(char*)&theKey.name);
  455.     
  456.         TextMode(srcBic); // reverse out the text you're about to draw
  457.         
  458.         // You may want to change the coordinates where the text is
  459.         // "reversed out" of window:
  460.         
  461.         MoveTo(2,window->portRect.bottom-45);
  462.         TextSize(10);
  463.         DrawText(output,0,strlen(output));
  464.         if (strlen((char*)&theKey.serialNumber))
  465.         {
  466.             sprintf(output,"Serial Number %s",(char*)&theKey.serialNumber);
  467.             MoveTo(2,window->portRect.bottom-30);
  468.         }
  469.     }
  470.     
  471.     SelectWindow(window);
  472.     
  473.     
  474.     // wait for the user to click the mouse or hit a key...
  475.     
  476.     userReacts=false;
  477.     do
  478.     {
  479.         if (WaitNextEvent(everyEvent, &event, 20, nil))
  480.         {    
  481.             switch (event.what)
  482.             {    
  483.                 case mouseDown:
  484.                 case keyDown:
  485.                 case autoKey:    
  486.                     userReacts=true;
  487.                     break;
  488.                 default:
  489.                     userReacts=false;
  490.                     break;
  491.             }
  492.         }
  493.     }
  494.     while (!userReacts);
  495.     
  496.     HideWindow(window);
  497.     DisposeWindow(window);
  498.     ReleaseResource((Handle)thePict);
  499. }    
  500.